/*
 * Created on Jan 23, 2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package bmoofxbridge.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;

import org.apache.commons.collections.MultiHashMap;
import org.apache.commons.collections.MultiMap;

/**
 * @author leonidr
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class Model {
    private Map accounts = new HashMap();
    private SortedSet transactions = new TreeSet(new TransactionDateComparator());
    private MultiHashMap accountTransactions = new MultiHashMap();
    private boolean tranDirty = false; 
    
    
    public void putAccount(Account act) {
        accounts.put(act.getAccountID(), act);
    }
    
    public Account getAccount(String id) {
    	syncronizeDataStruct();
        return (Account) accounts.get(id);
    }
    
    public void putTransaction(Transaction tansaction) {
    	tranDirty = true;
    	transactions.add(tansaction);        
    }
    
    public Collection getTransactionsByAccount(Account account) {
    	syncronizeDataStruct();    	
    	return ((Collection)accountTransactions.get(account));
        
    }
    
    /**
	 * 
	 */
	private void syncronizeDataStruct() {
		if (tranDirty){
			accountTransactions.clear();
			accounts.clear();
			
			//find duplicated transaction ids
			Map tranIds = new HashMap();
			for (Iterator iter = transactions.iterator(); iter.hasNext();) {
    			Transaction transaction = (Transaction) iter.next();
    			if (tranIds.containsKey(transaction.getId())){
    				String refAddition= String.valueOf(Math.round(Math.abs(transaction.getAmmount()*100)));
    				transaction.setRefNumber(transaction.getRefNumber()+refAddition);
    			}
    			tranIds.put(transaction.getId(),transaction);
			}
			
			
			
    		for (Iterator iter = transactions.iterator(); iter.hasNext();) {
    			Transaction transaction = (Transaction) iter.next();
    			
    			
    			accountTransactions.put(transaction.getAccount(),transaction);
    		}
			
			for (Iterator iterator = accountTransactions.keySet().iterator(); iterator.hasNext();) {
				Account account = (Account) iterator.next();
				putAccount(account);
			}
			
			tranDirty = false;
		}
	}

	public MultiMap getTransactionReportsByAccount(Account account) {
        MultiHashMap result = new MultiHashMap();
        Iterator iter = getTransactionsByAccount(account).iterator();
        
        while (iter.hasNext()) {
            Transaction transaction = (Transaction) iter.next();
            result.put(transaction.getStatementDate(), transaction);
        }

        return result;
    }
	
	public Collection getTransactions(Account account, Date date) {
		ArrayList result = new ArrayList();
		
		Iterator iter = getTransactionsByAccount(account).iterator();
        
        while (iter.hasNext()) {
            Transaction transaction = (Transaction) iter.next();
            if (transaction.getDate().getTime() >= date.getTime()){
            	result.add(transaction);
            }
        }
        return result;
		
	}
	
	public Collection getAccounts(boolean isCreditCard){
		syncronizeDataStruct();
		
		ArrayList resutl = new ArrayList();
		
		for (Iterator iter = accounts.values().iterator(); iter.hasNext();) {
			Account account = (Account) iter.next();
			
			if (!isCreditCard ^ (account instanceof CreditCardAccount)) {
				resutl.add(account);
			}
		}
		return resutl;
	}
    
    
    
    
    
    public class TransactionDateComparator implements Comparator {

        /* (non-Javadoc)
         * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
         */
        public int compare(Object arg0, Object arg1) {
        	int result=0;
            Transaction t0 = (Transaction) arg0;
            Transaction t1 = (Transaction) arg1;
            
            result = t0.getDate().compareTo(t1.getDate());
            
            if (0==result){
            	result = t0.hashCode()-t1.hashCode();
            }
            
            return result;           
        }

    }
    

}
